home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / lanutsrc.zip / INTERCOM.ASM < prev    next >
Assembly Source File  |  1991-03-13  |  25KB  |  912 lines

  1. INCLUDE \ASM\INCLUDE\BIOS.INC
  2. INCLUDE DEFS.INC
  3.  
  4. SOUND    EQU    61h
  5. TIMER    EQU    42h
  6. SPK_ON    EQU    3
  7.  
  8. VECTOR1    EQU    09h                     ; BIOS keyboard handler
  9. IROW    EQU    5            ; Starting row,col of window
  10. ICOL    EQU     10
  11. IHEIGHT EQU     5            ; Size of window    
  12. IWIDTH  EQU     63
  13.  
  14. ; status constants
  15. MAX_DEST EQU 16                         ; length of destination field
  16. MAX_MSG  EQU IWIDTH - 2            ; length of message field
  17. DEST     EQU 0                ; which field is active?
  18. MSG     EQU 0FFFFh
  19.  
  20. ; key codes
  21. UP      EQU     4800h            ; up arrow
  22. DN      EQU    5000h            ; down arrow
  23. LEFT    EQU     4B00h            ; left arrow
  24. RIGHT   EQU    4D00h            ; right arrow
  25. RETURN  EQU     1C0Dh            ; return key
  26. BACK    EQU     0E08h            ; backspace key
  27. INSERT  EQU     5200h
  28. DELETE  EQU     5300h
  29. HOME    EQU     4700h
  30. ENDKEY    EQU     4F00h                   ; End key
  31. ESCAPE    EQU    011Bh            ; Escape key
  32.  
  33. msv    SEGMENT
  34.     ASSUME  CS:msv
  35.     ASSUME  DS:msv
  36.     ASSUME  ES:msv
  37.     ASSUME  SS:NOTHING
  38.     ORG    0
  39. SEG_ORG    EQU    $    
  40.     ORG    100h
  41. main    PROC    FAR
  42. start:    jmp    init            ; Do initialization section
  43.  
  44. ;*******************************************************************
  45. ; LANOS VECTOR TSR portion of Message handler --
  46. ; The LANOS portion simply increments a message received flag and
  47. ; exits, leaving the actual processing of the message to an
  48. ; interrupt.
  49. ;*******************************************************************
  50. MSV_entry:    jmp first            ; skip data area
  51. msg_flag    dw    0
  52. old_msr        dd    ?
  53.  
  54. ;************************************************************************
  55. ; Start of actual LANOS message handler. Note that this handler DOES NOT
  56. ; call the previously chained vector -- while the intercom is popped up,
  57. ; no other message handling services will be activated.
  58. ;************************************************************************
  59. first:  
  60.     mov    cs:msg_flag,1        ; set the message received flag
  61.     iret                ; return to caller
  62.  
  63. ; ********************************************************************
  64. ;   Interrupt 09 - Keyboard interrupt handler
  65. ;   Thanks to Joe and Sam for demonstrating the right way to do it!
  66. ; ********************************************************************
  67. INT09_entry:
  68.     push ax
  69.     cmp  cs:busy,0            ; are we already popped up?
  70.     jnz   Done_09                         ; if so, continue
  71.     
  72.     in    al,60h                ; Read the character from the kbd
  73.     CMP  AL,CS:hotkey                  ; is it for us?
  74.     JNZ  Done_09                        ; if not, continue
  75.     
  76. ; Check the keyboard status bits to see if it's for us    
  77.     PUSH DS
  78.     MOV  AX,40H                         ; POINT TO THE BIOS
  79.     MOV  DS,AX
  80.     MOV  AL,DS:17H                      ; Get kbd status byte
  81.     POP  DS
  82.     AND  AL,CS:kbd_bits                 ; ARE THESE BITS ON?
  83.     CMP  AL,CS:kbd_bits                 ; WELL?
  84.     JNZ  Done_09                        ; NOPE NOT AT THIS TIME
  85.     
  86.  ; reset the keyboard
  87.     IN   AL,61H                         ; GET KBD CONTROL CODE
  88.     MOV  AH,AL
  89.     OR   AL,80H                         ; SET RESET BIT
  90.     OUT  61H,AL                         ; SEND RESET BACK
  91.     MOV  AL,AH                          ; GET BACK THE CONTROL CODE
  92.     OUT  61H,AL                         ; RESET DONE
  93.     MOV  AL,20H                         ; RESET HIGHEST IUS
  94.     OUT  20H,AL
  95.  
  96.     inc        cs:request        ; issue a pop up request
  97.     pop            ax
  98.     IRET                ; back to regularly scheduled program
  99.  
  100. Done_09:
  101.     POP AX
  102.     JMP  CS:old_vector1                 ; CONTINUE ON AS IF WE AREN'T HERE
  103.  
  104. ;*****************************************************************************
  105. ; Interrupt E0 handler --- this is apparently something that LANtastic uses
  106. ; internally to indicate when DOS is safe.
  107. ;*****************************************************************************
  108. INT_E0             DD   0
  109. DOSFREE:
  110.     PUSHF
  111.     CALL CS:old_vector2                 ; give everyone else a chance...
  112.     
  113.     cmp  cs:request,0                   ; have our services been requested?
  114.     jz   Done_E0            ; If not, skip this stuff
  115.     CMP  CS:busy,0                      ; Are we already busy?
  116.     JNZ  Done_E0                        ; If so, skip this stuff
  117.  
  118. ; Activate the pop up routine
  119.     dec  cs:request            ; cancel previous request
  120.     inc  cs:busy            ; set busy flag
  121.     call pop_up
  122.     dec     cs:busy            
  123.  
  124. Done_E0:
  125.     IRET
  126.  
  127. ;***********************************************************************
  128. ; Pop-up intercom
  129. ; When we're popped up, an Esc keypress will take us back to normal
  130. ; processing
  131. ;***********************************************************************
  132. pop_up    PROC    near
  133.     jmp    get_msg            ; bypass data area
  134.     
  135. ; housekeeping stuff and screen data area.
  136.         db    '■S'        ; ID string
  137. color        db    70h        ; Default window color
  138. hotkey        db    23        ; Activation key (I for now)
  139. kbd_bits    db      8        ; Alt
  140. busy        db    0            ; TSR status flag
  141. request         db      0               ; TSR activation request flag
  142. screen_data     dw     (IHEIGHT * IWIDTH) DUP (?)    
  143. from        db    'From: ',0      ; Onscreen prompts and instructions
  144. toquit        db    'Press Esc to exit',0
  145. old_vector1    dd      ?        ; old int vector
  146. old_vector2     dd      ?
  147. old_cursor    dw    ?        ; old cursor position
  148. msg_state       db      ?        ; old message processing flag
  149.  
  150. ; program status variables
  151. state        db    ?        ; current field id
  152. ins_flag    db    0        ; insert key state flag
  153. d_index        field_desc <0,0,16,OFFSET buffer.MB_machine>    
  154. m_index        field_desc <0,0,61,OFFSET buffer.MB_text>  
  155. c_field        dw    0        ; pointer to current field descriptor   
  156. done        db    0        ; completion flag
  157. buffer        message_buffer <>       ; message buffer for internal use
  158. inbuffer    message_buffer <>    ; buffer for incoming messages
  159. prompt1        db    "To:─────",0    ; prompt text messages
  160. prompt2        db    "Message:",0
  161.  
  162. ; stack information
  163. old_stk_seg    dw      ?               ; Calling program's stack info
  164. old_b_ptr    dw    ?
  165. old_stk_ptr    dw      ?
  166. new_stk_seg    dw      ?
  167. new_stk_ptr    dw    OFFSET TOS
  168.         dw    80 dup (?)    ; local stack data area
  169. TOS        equ    $        
  170.  
  171. get_msg:
  172.     @NewStack                  ; replace stack and save regs
  173.     push    cs            ; set all seg regs to current CS        
  174.     push    cs
  175.     pop    es
  176.     pop    ds
  177.     
  178. ; save calling cursor information
  179. IC1:
  180.     mov    ah,3            ; read cursor info
  181.     xor    bh,bh            ; for page 0
  182.     int    10h
  183.     mov    cs:old_cursor,dx    ; save cursor info
  184.  
  185. ;
  186. ; Replace the LANOS message service with our message handler
  187. ;
  188.  
  189. ; Save the message processing flag
  190.     mov    ax,5F9Ah
  191.     int    21h
  192.     mov    cs:msg_state,dl
  193.  
  194. ; Get addresss of old LANOS message handler 
  195.     mov     ax,5FE2h        ; Get old vector address
  196.     int    21h
  197.      mov    word ptr old_msr,bx     ; Save the location of the old vector
  198.      mov    word ptr old_msr+2,es
  199.     
  200. ; Set MSR vector to our routine
  201.      mov    ax,cs            ; segment address of our MSR
  202.      mov    es,ax
  203.      mov    bx,OFFSET MSV_entry    ; offset of MSR
  204.      mov    ax,5FE3h        ; set MSR vector function
  205.         int    21H
  206.         
  207. ;
  208. ; Tell message handler not to beep    
  209. ;        
  210.     mov    ax,5F9Bh        ; set message processing flag
  211.     mov    dl,2            ; deliver, but no beep
  212.     int    21h
  213.  
  214. ;
  215. ; save underlying screen and draw intercom window
  216. ;
  217.      mov    di, OFFSET screen_data  ; point to save area
  218.      mov    dh,IROW            ; starting screen row    
  219.      mov    cx,IHEIGHT
  220.  
  221. doRow:                                  ; For each row...
  222.     push    cx            ; save number of rows
  223.     mov    dl,ICOL            ; starting column on screen
  224.      call    CURSOR                  ; move cursor to row start
  225.     mov    cx,IWIDTH        ; number of columns
  226.     
  227. DoCol:                  ; For each character
  228.        push    cx            ; save char count    
  229.        @GetChAtr    0                 ; Get the char and attribute
  230.        stosw                            ; move it to the save area
  231.  
  232.        inc     dl            ; move cursor
  233.        call     CURSOR
  234.        
  235.        pop    cx            ; retrieve char count
  236.        loop    SHORT DoCol        ; go back for next char
  237.        
  238.        inc    dh            ; point to next screen row
  239.        pop    cx            ; retrieve row count
  240.        loop    SHORT    DoRow
  241.        
  242. ; Draw intercom window
  243.        DRAW_LINE       '┌','─','╖',IROW
  244.  
  245.        MOVE_CURSOR    IROW,ICOL+1
  246.        mov        di, OFFSET from
  247.        call        PRT_STR
  248.     
  249.        DRAW_LINE       '│',' ','║',IROW+1
  250.     
  251.        DRAW_LINE       '├','─','╢',IROW+2
  252.  
  253.        DRAW_LINE       '│',' ','║',IROW+3
  254.     
  255.        DRAW_LINE       '╘','═','╝',IROW+4 
  256.  
  257.        MOVE_CURSOR    IROW+4,ICOL+45
  258.        mov        di, OFFSET toquit
  259.        call        PRT_STR
  260.  
  261. ;
  262. ;  Initialize variables
  263. ;
  264.        push    cs            ; set all seg regs to current CS        
  265.        push    cs
  266.        pop    es
  267.        pop    ds
  268.     
  269.        mov    done,0
  270.  
  271.        mov    c_field,OFFSET d_index    ;destination field
  272.  
  273. ;
  274. ; Get user input
  275. ;
  276.        mov    dh,IROW + 2        ; display field name prompt
  277.        mov    dl,ICOL + 1
  278.        call    CURSOR
  279.        mov    di,OFFSET prompt1    
  280.        call     PRT_STR
  281.     
  282.        mov    dh,IROW + 3             ; display destination prompt
  283.        mov    dl,ICOL + 1
  284.        call    CURSOR
  285.        mov    di,OFFSET buffer.MB_machine
  286.        call    PRT_STR
  287.  
  288.        mov    cs:state,DEST        ; set field to destination
  289.         
  290.        mov    dh,IROW + 3        ; move cursor to start of field
  291.        mov    dl,ICOL + 1
  292.        add    dl,d_index.FD_index     ; move to last cursor pos
  293.        mov    msg_flag,1        ; set up to display last message
  294.  
  295. Get_input:
  296.        cmp    msg_flag,1              ; see if a message is ready
  297.        jne    GI1        
  298.        call    SHOW_MESSAGE        ; if we've got one, show it.
  299. GI1:
  300.        call    CURSOR            ; move cursor to appropriate place
  301.        mov    ax,0100h        ; get keyboard status fn.
  302.        int    16h
  303.        jz     Get_input        ; if not, go back
  304.     
  305.        xor    ax,ax            ; Read keyboard char fn.
  306.        int    16h
  307. ;
  308. ; Process each keystroke
  309. ;    
  310.        cmp    ax,UP
  311.        jne    N1
  312.        jmp    Toggle
  313. N1:    cmp    ax,DN   
  314.        jne    N2
  315. Toggle:                    ; switch fields
  316.        cmp    state,DEST        ; are we in destination state?
  317.        jne    toggle2            ; if not, go to other switch
  318.  
  319.        call    CLEAR_FIELD        ; clear the field
  320.        not    state            ; switch to message state
  321.        mov    c_field, OFFSET m_index ; switch to correct field desc.
  322.     
  323.        mov    dh,IROW + 3        ; display message text
  324.        mov    dl,ICOL + 1
  325.        call    CURSOR
  326.        mov    di, OFFSET buffer.MB_text
  327.        call    PRT_STR
  328.     
  329.        mov    dh,IROW + 2        ; display message prompt
  330.        mov    dl,ICOL + 1
  331.        CALL    CURSOR
  332.        mov    di,OFFSET prompt2    ; display MESSAGE: prompt
  333.        call PRT_STR
  334.     
  335.        mov    dh,IROW + 3        ; move cursor to proper spot
  336.        mov    dl,ICOL + 1
  337.        mov    si,c_field        ; get address of field record
  338.        add    dl,[si].fd_index
  339.        call    CURSOR
  340.        jmp    Break
  341. Toggle2:    
  342.        call    CLEAR_FIELD        ; clear the field
  343.  
  344.        not    state            ; switch to message state
  345.        mov    c_field, OFFSET d_index ; switch to correct field desc.
  346.     
  347.        mov    dh,IROW + 3             ; display destination 
  348.        mov    dl,ICOL + 1
  349.        call    CURSOR
  350.        mov    di, OFFSET buffer.MB_machine
  351.        call    PRT_STR
  352.  
  353.        mov    dh,IROW + 2        ; display destination prompt
  354.        mov    dl,ICOL + 1
  355.        call    CURSOR
  356.        mov    di,OFFSET prompt1    
  357.        call     PRT_STR
  358.     
  359.        mov    dh,IROW + 3        ; move cursor to proper spot
  360.        mov    dl,ICOL + 1
  361.        mov    si,c_field        ; get address of field record
  362.        add    dl,[si].fd_index    ; get current cursor position
  363.        call    CURSOR
  364.        jmp    Break
  365.  
  366. N2:    cmp    ax,LEFT
  367.     jne    N3
  368.     mov    si,c_field        ; check cursor position
  369.     cmp    [si].FD_index,0        ; if at left edge, do nothing
  370.     jne    LCONT
  371.     jmp    Break
  372. LCONT:    
  373.     dec    [si].FD_index        ; move one position left
  374.     dec    dl            ; move cursor
  375.     jmp    Break
  376. N3:    cmp    ax,RIGHT
  377.     jne    N4
  378.     mov    si,c_field        ; check cursor position
  379.     mov    ah,[si].FD_index
  380.     cmp    ah,[si].FD_maxlen
  381.     jl    RCONT
  382.     jmp    Break
  383. RCONT:                        ; if at right edge, do nothing
  384.     inc    [si].FD_index        ; move one position right
  385.     inc    dl            ; move cursor
  386.     jmp    Break
  387. N4:    cmp    ax,BACK
  388.     jne    N5
  389.     mov    si,c_field        ; check cursor position
  390.     cmp    [si].FD_index,0        ; if at left edge, do nothing
  391.     jg    BCONT
  392.     jmp    Break
  393. BCONT:    
  394.     dec    [si].FD_index        ; move one column left
  395.     dec    dl            ; move cursor too
  396.     call    CURSOR
  397.     
  398.     xor    cx,cx
  399.     mov    cl,[si].FD_index    ; current pointer position
  400.     mov    si,[si].FD_data        ; offset of start of current string
  401.     add    si,cx            ; point to current position
  402.     
  403.     call    DELETE_CHAR
  404.     jmp    Break
  405.  
  406. N5:    cmp    ax,RETURN
  407.     jne    N6
  408. ; see if we're ready to send a message
  409.     cmp    d_index.FD_length,0    ; see if destination is set
  410.     jg    RET1
  411.     jmp    Toggle            ; if not, just switch fields
  412. RET1:    
  413.     cmp    m_index.FD_length,0    ; see if message is ready
  414.     jg    RET2            ; if not, just switch fields
  415.     jmp    Toggle
  416.  
  417. ; if so, compose the message and send it    
  418. RET2:
  419.     mov    ax,5F98H        ; send message interrupt
  420.     mov    si,OFFSET buffer    ; message buffer
  421.     int    21h            ; send message
  422.     
  423. ; clear fields and get ready for next message
  424.     call     CLEAR_FIELD
  425.     mov    m_index.FD_length,0    ; zero pointers an length for message
  426.     mov    m_index.FD_index,0
  427.     mov    d_index.FD_length,0    ; zero pointers and length for dest
  428.     mov    d_index.FD_index,0
  429.     mov    buffer.MB_machine,0    ; zero message and dest buffers    
  430.     mov    buffer.MB_text,0
  431.     mov    state,MSG
  432.     jmp    Toggle            ; toggle state to DEST again...
  433.     jmp    Break
  434. N6:    cmp    ax,INSERT
  435.     jne    N7
  436.     not    ins_flag        ; toggle insert flag
  437.     jmp    Break
  438. N7:    cmp    ax,DELETE
  439.     jne    N8
  440.     mov    si,c_field
  441.     cmp    [si].FD_length,0    ; if length is 0, nothing to delete    
  442.     jg    DELCONT
  443.     jmp    Break
  444. DELCONT:
  445.     xor    cx,cx
  446.     mov    cl,[si].FD_index    ; current pointer position
  447.     mov    si,[si].FD_data        ; offset of start of current string
  448.     add    si,cx            ; point to current position
  449.     
  450.     call    DELETE_CHAR
  451.     jmp    Break
  452. N8:    cmp    ax,HOME
  453.     jne    N9
  454.     xor    bx,bx            ; get us a zero to work with
  455.     mov    si,c_field        ; get current field address
  456.     mov    [si].FD_index,bl  
  457.     mov    dl,ICOL + 1        ; reset current cursor position
  458.     jmp    Break
  459. N9:     cmp    ax,ESCAPE
  460.     jne    N10
  461.     mov    done,1
  462.     jmp    Break
  463. N10:    cmp    ax,ENDKEY 
  464.     jne    Default
  465.     mov    si,c_field
  466.     mov    bl,[si].FD_length
  467.     mov    [si].FD_index,bl
  468.     mov    dl,ICOL + 1
  469.     add    dl,bl
  470.     jmp    Break
  471. Default:
  472.     mov    si,c_field
  473.     mov    bl,[si].FD_length
  474.     mov    bh,[si].FD_maxlen
  475.         cmp    bl,bh            ; see if we've hit the end of field
  476.         jge    Break            ; if so, do nothing
  477.         
  478.         cmp    state,DEST        ; see if we're in destination field
  479.         jne    DEFCON            ; if not, don't shift 
  480.         call    UPCASE
  481.  
  482. DEFCON:
  483.     cmp    ins_flag,0        ; see if we're in insert state
  484.     je    OVERWRITE        ; if not, overwrite
  485.     call    INSERT_CHAR
  486.     jmp    Break
  487.  
  488. OVERWRITE:
  489.     mov    ah,[si].FD_index    ; save the character
  490.     CALL    STORE_CHAR
  491.  
  492.         PUTC    al,1            ; write character
  493.     inc    dl            ; increment cursor position
  494.     mov    cl,[si].FD_index    ; get current position
  495.     inc    cl                  ; increment char pointer
  496.     mov    [si].FD_index,cl    ; save new pointer
  497.     
  498.     cmp    cl,[si].FD_length    ; are we appending to the string?
  499.     jl    Break            ; if not, we're done    
  500.  
  501.         mov    ah,[si].FD_length    ; otherwise, get length pointer
  502.         inc    ah            ; increment string length
  503.     mov    [si].FD_length,ah    ; save new length
  504.     xor    al,al            ; save a terminating NULL char
  505.     CALL    STORE_CHAR
  506.     
  507. Break:
  508.     cmp    cs:done,1
  509.     je    shutdown
  510.     jmp    get_input
  511.     
  512. shutdown:    
  513. ;
  514. ; Restore screen data
  515. ;
  516.      mov    si, OFFSET screen_data  ; point to save area
  517.      
  518.      
  519.      mov    dh,IROW
  520.     mov    cx,IHEIGHT        ; number of rows to do
  521.     
  522. doRow1:                                 ; For each row...
  523.     push    cx            ; save number of rows
  524.     mov    dl,ICOL            ; starting column on screen
  525.      call    CURSOR                  ; move cursor to row start
  526.     mov    cx,IWIDTH        ; number of columns
  527.     
  528. DoCol1:                  ; For each character
  529.        push    cx            ; save char count    
  530.        
  531.        lodsw                ; get next word from save area
  532.        @PutChAtr   al,ah,0,1        ; write next picture char
  533.        
  534.        inc     dl            ; move cursor
  535.        call     CURSOR
  536.        
  537.        pop    cx            ; retrieve char count
  538.        loop    SHORT DoCol1        ; Go back for next char
  539.        
  540.        inc    dh                      ; point to next row
  541.        pop    cx            ; retrieve row count
  542.        loop    SHORT DoRow1        ; Go back for next char
  543.  
  544. ;
  545. ; Restore previous LANOS message handler.
  546. ;
  547.  
  548. ; Set MSR vector to original routine
  549.      mov    ax,word ptr old_msr+2    ; segment addr of old routine
  550.      mov    es,ax
  551.      mov    bx,word ptr old_msr    ; offset of old routine
  552.      mov    ax,5FE3h        ; set MSR vector fn.
  553.      int    21H
  554.  
  555. ;
  556. ; Restore the message processing flag
  557. ;        
  558.     mov    ax,5F9Bh        ; set message processing flag
  559.     mov    dl,cs:msg_state     ; back to it's previous state
  560.     int    21h
  561.  
  562.  
  563. ; restore cursor to original position
  564.     mov    ah,2            ; set cursor position
  565.     mov    bh,0            ; for page 0
  566.     mov    dx,cs:old_cursor
  567.     int    10h                   
  568.        
  569. bypass:
  570.     @OldStack                       ; restore caller's stack
  571.     ret                ; return to caller
  572. pop_up ENDP
  573.  
  574. ;*********************************************************************
  575. ; Subroutines
  576. ;********************************************************************
  577. ; Move cursor -- row in dh, col in dl
  578. CURSOR  PROC    NEAR
  579.     push    ax
  580.     push    bx
  581.     push    cx
  582.     
  583.     @SetCurPos    dl,dh,0 
  584.     
  585.         pop    cx
  586.         pop    bx
  587.         pop    ax
  588.         ret
  589. CURSOR  ENDP
  590. PRT_STR    PROC    NEAR
  591. ;
  592. ; Write ASCIIZ string pointed to by ES:DI at current cursor position
  593. ;
  594. L3:
  595.     mov    al,es:[di]        ; get the character
  596.     or    al,al            ; See if it's a zero
  597.     jz    L4            ; Yes- we're done
  598.     mov    bx,7            ; display page 0, fg color 7
  599.     mov     ah,0Eh            ; Write char / tty mode
  600.     int     10h            ; Display the character
  601.     inc    di            ; get the next char
  602.     jmp    short L3
  603. L4:
  604.     ret    
  605. PRT_STR    ENDP
  606.  
  607. CLEAR_FIELD PROC  NEAR
  608. ;
  609. ; clear the input field
  610. ;
  611.         mov    dh,IROW + 3
  612.         mov    dl,ICOL + 1
  613.     call     CURSOR
  614.  
  615.     mov    si,c_field
  616.     xor    cx,cx
  617.     mov    cl,[si].FD_maxlen    
  618.     PUTC    ' ',cx
  619.  
  620.         mov    dh,IROW + 3
  621.         mov    dl,ICOL + 1
  622.     call     CURSOR
  623.     
  624.     ret
  625. CLEAR_FIELD ENDP                    
  626.  
  627. DELETE_CHAR PROC NEAR
  628. ;
  629. ; Gets rid of a the character in the asciiz string currently 
  630. ; pointed to by DS:SI. Assumes that ES is also pointing to
  631. ; the string's segment. Handles all screen IO, assuming the
  632. ; cursor was positioned at the character to be deleted.
  633. ;    
  634.     push    dx        ; save starting cursor position
  635.     
  636.     mov    di,si        ; save offset of char to go
  637.     push    di        ; save offset for printing later
  638.     
  639.     inc    si        ; skip the current char
  640. DL1:    
  641.     lodsb            ; get the next char
  642.     stosb            ; save it in the previous slot
  643.     cmp    al,0        ; is a terminator?
  644.     jne    DL1        ; if not, go back for the next char
  645.     
  646.     pop    di        ; get the old string location back
  647.     call    PRT_STR        ; print the modified string
  648.     PUTC    ' ',1
  649.     pop    dx        ; restore starting cursor position
  650.     
  651.     mov    si,c_field    ; update housekeeping info
  652.     dec    [si].FD_length
  653.     
  654.     ret
  655. DELETE_CHAR ENDP        
  656.  
  657. STORE_CHAR PROC NEAR
  658. ;
  659. ; Store a character in the current field string. Takes the character
  660. ; in Al and the position in the string in AH. Uses the BX register
  661. ;
  662.     push    bx            ; save the registers used
  663.     push    cx            
  664.     
  665.     xor    cx,cx            ; clear CX ...
  666.     mov    cl,ah            ; load w/ offset value
  667.     
  668.         mov    bx,c_field
  669.         mov    bx,[bx].FD_data        ; offset of string buffer
  670.         add    bx,cx            ; + position in buffer
  671.         mov    [bx],al            ; save character
  672.         
  673.         pop    cx            ; restore registers
  674.         pop    bx
  675.         ret
  676. STORE_CHAR ENDP    
  677.  
  678. UPCASE    PROC    NEAR
  679. ;
  680. ; If the character in al is a lower case letter, convert to uppercase
  681. ;
  682.     cmp    al,97            ; compare to 'a'
  683.     jl    SHL1            ; if lower, return
  684.     cmp     al,122            ; compare to 'z'
  685.     jg    SHL1            ; if higher, return
  686.     sub    al,32            ; convert to uppercase
  687. SHL1:
  688.     ret
  689. UPCASE    ENDP        
  690.  
  691. INSERT_CHAR    PROC    NEAR
  692. ;
  693. ; Inserts the character currently in AL in the current string at the 
  694. ; location indicated by AH. Assumes that ES is also pointing to the string's
  695. ; segment and that the cursor is located at the right spot.
  696. ;
  697.     push    dx            ; save starting cursor position
  698.     
  699.     xor    cx,cx            ; point SI to correct location
  700.     mov    si,c_field
  701.     mov    cl,[si].FD_index
  702.     mov    si,[si].FD_data
  703.     add    si,cx
  704.     mov    di,si            ; copy string pointer to DI
  705.  
  706. IL1:
  707.     mov    ah,[si]            ; old character in ah
  708.     mov    [si],al            ; new char in al
  709.     mov    al,ah            ; move old to new
  710.     
  711.     inc    si            ; move to next char position
  712.     and    ah,ah            ; see if it's a zero
  713.     jnz    IL1            ; if not, go back for next one
  714.  
  715. ; display the string
  716.     CALL     PRT_STR            
  717.     
  718. ; Update housekeeping information
  719.     mov     si,c_field
  720.     inc    [si].FD_index
  721.     inc    [si].FD_length
  722.     
  723.     pop    dx            ; restore cursor location
  724.     inc    dl
  725.     ret
  726. INSERT_CHAR ENDP    
  727.  
  728. SHOW_MESSAGE PROC NEAR
  729. ; display message in message area
  730. ;
  731.     push    dx            ; save current cursor loc
  732.  
  733.     mov    ax,5F99h        ; get last message fn.
  734.     mov    di,OFFSET inbuffer  ; point to receive area
  735.     int    21h            ; get the message
  736.     
  737. ;
  738. ; Display last received message and previous contents of message buffer
  739. ;       
  740.         mov    dh,IROW                 ; display originator's name
  741.         mov    dl,ICOL + 7
  742.         call     CURSOR
  743.         PUTC    '─',16            ; clear field
  744.         call    CURSOR
  745. ; get rid of trailing spaces
  746.         mov    di, OFFSET inbuffer.MB_originator
  747.         mov    al,32            ; scan for spaces
  748.         mov    cx,16            ; max field length
  749. repnz    scasb
  750.     mov    [di],ch            ; terminate string
  751. ; print the string
  752.         mov    di, OFFSET inbuffer.MB_originator
  753.         call    PRT_STR
  754.  
  755. ; display message text
  756. ; -- first make silly sound
  757.     mov    al,0B6h            ; timer setup value
  758.     out    43h,al            ; tell timer a count's coming
  759.     mov    ax,397            ; frequency -- about 3000 hertz
  760.     out    42h,al            ; send the count
  761.     mov    al,ah            
  762.     out    42h,al
  763.  
  764.     xor    ah,ah
  765.     in    al,SOUND        ; turn on speaker
  766.     or    al,SPK_ON
  767.     out    SOUND,al          
  768.     
  769.         mov    dh,IROW + 1             ; display message text
  770.         mov    dl,ICOL + 1
  771.      call    CURSOR    
  772.      PUTC    ' ',61
  773.         call    CURSOR
  774.         mov    di, OFFSET inbuffer.MB_text
  775.         call    PRT_STR
  776.  
  777. ; turn off speaker
  778.      in    al,sound    
  779.     and    al, NOT SPK_ON
  780.      out    sound,al
  781.         
  782.         pop    dx                      ; restore cursor position
  783.         mov    msg_flag,0        ; reset received flag    
  784.         ret
  785. SHOW_MESSAGE    ENDP      
  786. ; write character in al at current cursor position 
  787. ; char count should be in CX
  788. PUTCHAR        PROC    NEAR
  789.     mov    bl,color
  790.     xor    bh,bh
  791.     mov    ah,09h
  792.     int    10h
  793.     ret
  794. PUTCHAR        ENDP    
  795.  
  796. ;
  797. ; Draw one line of INTERCOM's screen window
  798. ;
  799. LINE        PROC    NEAR
  800.     push    bx
  801.     push    bx
  802.     push    ax
  803.     push    bx
  804.     
  805.     MOVE_CURSOR    bh,ICOL         ; move to beginning of line
  806.     PUTC        al,1            ; display leading character
  807.     
  808.     pop    bx            ; retrieve row
  809.     MOVE_CURSOR    bh,ICOL+1       ; move to 2nd char of line
  810.     pop    ax              ; retrieve char to display 
  811.     mov    al,ah            ; move char to al
  812.     PUTC        al,IWIDTH-2     ; display line 'middle' character
  813.  
  814.     pop    bx                      ; retrieve row coords
  815.     MOVE_CURSOR    bh,ICOL+IWIDTH-1; move to last char of line
  816.     pop    ax            ; retrieve character
  817.     PUTC        al,1            ; display line 'end' character
  818.     
  819.     ret
  820.     
  821. LINE    ENDP    
  822.     
  823.         
  824.  
  825. LAST_BYTE    EQU $
  826.  
  827. ;
  828. ;    Initialization -- thrown away after load
  829. ;
  830.  
  831. title1    db    "    SoftMagic Resident Intercom V1.0 for LANtastic",13,10,0
  832. title2    db    "Copyright 1989 by SoftMagic, Inc. All rights Reserved.",13,10,0
  833. title3    db    "     LANtastic is a trademark of Artisoft, Inc.",13,10,0
  834. title4    db     13,10,"The SoftMagic Resident Intercom is already installed.",13,10,0
  835.  
  836. IFDEF    SHAREWARE
  837. title5  db      7,"Thanks for trying this unregistered ShareWare Version!",7,7,13,10,0
  838. ENDIF
  839.  
  840. init:    mov    cs:busy,1           ; prevent activation
  841.     @NewStack            ; Set up local stack
  842.  
  843. ; Display title messge
  844.     mov     di,OFFSET title1
  845.     call    PRT_STR
  846.     mov    di,OFFSET title2
  847.     call    PRT_STR
  848.     mov    di,OFFSET title3
  849.     call     PRT_STR
  850.     
  851. IFDEF    SHAREWARE    
  852.     mov    di,OFFSET title5
  853.     call    PRT_STR
  854. ENDIF    
  855.  
  856.     
  857. ;
  858. ; Get the location of the DOS Busy flag
  859. ;
  860. ;       mov    ax,3400h                ; Flag is zero if DOS is safe
  861. ;       int    21h
  862. ;       mov    dos_busy_seg,es
  863. ;       mov    dos_busy_offs,bx
  864.     
  865. ;
  866. ; Replace the keyboard interrupt handler
  867. ;
  868.      mov     ah,35h            ; Get int vector fcn.
  869.      mov    al,VECTOR1        ; vector to get
  870.      int     21h            ; Get the silly thing
  871.  
  872. ; Save the old vector
  873.     
  874.      mov    word ptr old_vector1,bx    ; Save location of old vector
  875.      mov    word ptr old_vector1+2,es
  876. ;    
  877. ; Set Interrupt vector to our routine
  878. ;
  879.      mov    ah,25h            ; Set vector fcn
  880.      mov    al,VECTOR1           ; Vector to replace
  881.      mov    dx,OFFSET INT09_entry   ; Pointer to our routine
  882.      int    21h            ; Replace the vector            
  883.  
  884. ;
  885. ; Replace LANtastic's internal DOS free vector
  886. ;
  887.     MOV  AX,5FE0H
  888.     INT  21H                            ; GET THE DOS FREE VECTOR
  889.     MOV  WORD PTR old_vector2,BX
  890.     MOV  WORD PTR old_vector2+2,ES
  891.  
  892. ;
  893. ; Set vector to our routine
  894. ;
  895.     push cs
  896.     pop  es    
  897.         MOV  BX,OFFSET DOSFREE
  898.         MOV  AX,5FE1H
  899.         INT  21H                           
  900.  
  901. ; Terminate and stay resident
  902.      @OldStack            ; Restore caller's stack
  903.      mov    cs:busy, 0              ; Enable pop-up
  904.      mov    dx,(offset LAST_BYTE - SEG_ORG + 15) shr 4
  905.      mov    ah,31h                  ; free memory and leave
  906.      int     21h
  907. main    ENDP
  908. msv    ENDS
  909. END    start                        
  910.                     
  911.